package com.myself.common.repository


import com.myself.common.entity.BaseEntity
import com.myself.common.page.Page
import com.myself.common.page.PageResult
import com.myself.common.table.BaseTable
import org.ktorm.dsl.*
import org.ktorm.entity.*
import org.ktorm.schema.ColumnDeclaring

abstract class BaseRepository<T : BaseEntity<T>, B : BaseTable<T>>(
    val sequence: EntitySequence<T, B>
) {

    open fun findAll(): List<T> {
        return sequence.sortedBy { it.createTime.desc() }.toList()
    }

    open fun findAll(page: Page): PageResult<T> {
        return sequence.sortedBy { it.createTime.desc() }
            .pageList(page)
    }

    open fun addOne(one: T): Int {
        return sequence.add(one)
    }

    open fun findById(id: Int): T? {
        return sequence.find { it.id eq id }
    }

    open fun findLast(): T? {
        return sequence
            .filter { it.createTime.isNotNull() }
            .sortedBy { it.createTime.desc() }
            .firstOrNull()
    }

    open fun updateOne(one: T): Int {
        return sequence.update(one)
    }



    open fun deleteOne(one: T): Int {
        return sequence
                .find { it.id eq one.id }
                ?.delete() ?: 0
    }

    open fun findOneBy(condition: (B) -> ColumnDeclaring<Boolean>): T?{
        return sequence.find(condition)
    }

    open fun findBy(condition: (B) -> ColumnDeclaring<Boolean>): List<T>{
        return sequence.filter(condition).toList()
    }

    open fun findPageListBy(page: Page, condition: (B) ->ColumnDeclaring<Boolean>): PageResult<T>{
        return sequence.filter(condition).pageList(page)
    }
}

/**
 *  EntitySequence的分页查询，最终返回仍然是一个EntitySequence
 *
 */

fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.page(page: Int, pageSiz: Int): EntitySequence<E, T> {
    return this.withExpression(expression.copy(limit = pageSiz, offset = page * pageSiz))
}

/**
 *  EntitySequence的分页查询，最终返回仍然是一个EntitySequence
 *  此函数传入的[page]会直接进行减一操作
 *
 */
fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.page0(page: Int, pageSiz: Int): EntitySequence<E, T> {
    return this.withExpression(expression.copy(limit = pageSiz, offset = (page - 1) * pageSiz))
}


/**
 * 返回Query的分页，返回Query
 */

fun Query.page(page: Int, pageSiz: Long): Query {
    return this.limit((pageSiz * page).toInt(), pageSiz.toInt())
}

/**
 * 返回Query的分页，返回Query
 * 此函数传入的[page]会直接进行减一操作
 */
fun Query.page0(page: Int, pageSiz: Long): Query {
    return this.limit((pageSiz * page - 1).toInt(), pageSiz.toInt())
}

fun <T : BaseEntity<T>, B : BaseTable<T>> EntitySequence<T, B>.pageList(page: Page): PageResult<T> {
    val (current,size )  =page
    val offset = ((current - 1) * size).coerceAtLeast(0)
    val pageExpression = this.withExpression(expression.copy(limit = size, offset = offset)).sortedBy { it.id.desc() }
    val pagedList = pageExpression.toList()
    val totalCount = this.count()
    val totalPages = if ((totalCount % size).toLong() == 0L) {
        totalCount / size
    } else {
        totalCount / size + 1
    }
    return PageResult(
        total = totalCount,
        records = pagedList,
        size = size,
        current = current ,
        totalPages = totalPages
    )
}


